﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 
// See License.txt in the project root for license information.

using System;
using System.Fabric;
using System.Net.Sockets;

namespace ActorGatewayService
{
    public static class GatewayServiceHost
    {
        private static void Usage()
        {
            Console.WriteLine("Actor Framework Gateway Service");
            Console.WriteLine("Use this to connect to an existing Actor Runtime installation, either locally");
            Console.WriteLine("or in Azure.  This is intended to be run precisely once per machine, in Azure");
            Console.WriteLine("possibly as a service.  But there is a standalone mode for testing gateway");
            Console.WriteLine("support as well.");
            Console.WriteLine();
            Console.WriteLine("  ActorGatewayService [-standalone [-serverport n]]");
            Console.WriteLine();
            Console.WriteLine("  -standalone is for testing the gateway outside of an Azure environment.");
            Console.WriteLine("  -serverport is the TCP port number to connec to.  Default is 19000.");
        }

        public static void Main(string[] args)
        {
            bool standalone = false;
            int serverPort = 19000;  // For connecting to the Actor Runtime

            if (args.Length > 0)
            {
                for(int argIndex = 0; argIndex < args.Length; argIndex++)
                {
                    if (args[argIndex].ToLower().Equals("-standalone"))
                    {
                        standalone = true;
                    }
                    else if (args[argIndex].ToLower().Equals("-serverport"))
                    {
                        if (args.Length < argIndex + 2)
                        {
                            Console.Error.WriteLine("Missing argument for -serverport.  Specify a port number like 19000.");
                            Usage();
                            return;
                        }
                        serverPort = Int32.Parse(args[++argIndex]);
                    }
                    else
                    {
                        Usage();
                        return;
                    }
                }
            }

            if (standalone)
            {
                MessageLogger.Initialize("ActorGatewayConsoleOutput.txt");
                MessageLogger.WriteLine("Starting ActorGatewayTcpListener, using a server port of {0}...", serverPort);
                var listenerIPv4 = new ActorGatewayTcpListener(new Uri("net.tcp://localhost:8506"), AddressFamily.InterNetwork, serverPort);
                MessageLogger.WriteLine("IPv4 listener started!  Listener endpoint = {0}", listenerIPv4.Endpoint);
                var listenerIPv6 = new ActorGatewayTcpListener(new Uri("net.tcp://[::1]:8506"), AddressFamily.InterNetworkV6, serverPort);
                MessageLogger.WriteLine("IPv6 listener started!  Listener endpoint = {0}", listenerIPv6.Endpoint);
                MessageLogger.Write("Press <Enter> to exit...");
                Console.ReadLine();
                listenerIPv4.Close();
                listenerIPv6.Close();
                Environment.Exit(0);
            }

            FabricRuntime fabricRuntime = null;
            try
            {
                MessageLogger.Initialize("ConsoleOutput.txt");
                // Create a Windows Fabric Runtime
                MessageLogger.Write("Creating an Actor Runtime Service ...");
                //FabricRuntime fabricRuntime = FabricRuntime.FabricCreateRuntime();
                fabricRuntime = FabricRuntime.Create();
                MessageLogger.WriteLine("Done.");

                // Register Gateway Service with the runtime
                MessageLogger.WriteLine();
                MessageLogger.Write("Registering GatewayService ...");
                fabricRuntime.RegisterServiceType("ActorGatewayService", typeof(ActorGatewayService));
                MessageLogger.WriteLine("Done.");

                // Wait for WindowsFabric to place services in this process
                MessageLogger.WriteLine();
                MessageLogger.WriteLine("Waiting for Actor Runtime to place GatewayService instances.");
                MessageLogger.WriteLine("Press [Enter] to exit ..");
                MessageLogger.WriteLine();
                Console.ReadLine();
            }
            catch (Exception e)
            {
                MessageLogger.WriteLine("Caught Exception: {0}", e);
                MessageLogger.WriteLine("Press enter to terminate", e);
                Console.ReadLine();
            }
            finally
            {
                if (fabricRuntime != null)
                {
                    ((IDisposable)fabricRuntime).Dispose();
                }

                MessageLogger.Close();
            }
        }
    }
}
